/*************************************************************************************
*Copyright (c) 2011, Intel Mobile Communications GmbH. 
*All rights reserved.
*
*Redistribution and use in source and binary forms, with or without
*modification, are permitted provided that the following conditions are met:
*    * Redistributions of source code must retain the above copyright
*      notice, this list of conditions and the following disclaimer.
*    * Redistributions in binary form must reproduce the above copyright
*      notice, this list of conditions and the following disclaimer in the
*      documentation and/or other materials provided with the distribution.
*    * Neither the name of the <organization> nor the
*      names of its contributors may be used to endorse or promote products
*      derived from this software without specific prior written permission.
*
*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
*ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
*WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
*DISCLAIMED. IN NO EVENT SHALL INTEL MOBILE COMMUNICATIONS GMBH. BE LIABLE FOR ANY
*DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
*(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
*LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
*ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
*(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
*SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*************************************************************************************/



#ifndef CEF_ROUTES_H
#define CEF_ROUTES_H
#include <string>
#include <vector>
#ifdef _DEBUG
#include <iostream>
#endif
enum cef_routing_policy {SRCROUTING, DISTROUTING, FBDR, FDOR};
class cef_src_route
{
	protected:
	unsigned source_id;
	unsigned destination_id;
	std::vector<unsigned>* switch_output_port_ids;
	double weight;
	public:
	cef_src_route();
	cef_src_route(unsigned,unsigned,std::vector<unsigned>*, double);
	~cef_src_route();
	//Setters
	void setSrcID(unsigned);
	void setDstID(unsigned);
	void setSOPI(std::vector<unsigned>*);
	void setWeight(double);
	//Getters
	unsigned getSrcID();
	unsigned getDstID();
	std::vector<unsigned>* getSOPI();
	double getWeight();
#ifdef _DEBUG
	void print();
#endif
};
class cef_routes_switch
{
	protected:
	unsigned id;
	unsigned outport;
	unsigned linknum;
	public:
	cef_routes_switch();
	cef_routes_switch(unsigned, unsigned, unsigned);
	~cef_routes_switch();
	//Setters
	void setID(unsigned);
	void setOutPort(unsigned);
	void setLinkNum(unsigned);
	//Getters
	unsigned getID();
	unsigned getOutPort();
	unsigned LinkNum();
	#ifdef _DEBUG
	void print();
	#endif

};
class cef_sourcerouting
{
	protected:
	std::vector<cef_src_route*>* routes;
	public:	
	cef_sourcerouting();
	cef_sourcerouting(std::vector<cef_src_route*>*) ;
	~cef_sourcerouting();
	//Setters
	void setRoutes(std::vector<cef_src_route*>*);
	//Getters
	std::vector<cef_src_route*>* getRoutes();
	#ifdef _DEBUG
	void print();
	#endif
};

class cef_routing_table
{
	protected:	
	unsigned switch_id;
	unsigned destination_id;
	unsigned input_port_id;
	std::vector<std::pair<unsigned,double>* >* output_ports;//(id,weight)
	public:
	cef_routing_table();
	cef_routing_table(unsigned, unsigned,unsigned, std::vector<std::pair<unsigned,double>* >*);
	~cef_routing_table();
	//Setters
	void setSwID(unsigned);
	void setDstID(unsigned);
	void setInpID(unsigned); 
	void setOutPorts(std::vector<std::pair<unsigned, double>* >*);
	//Getters
	unsigned getSwID();
	unsigned getDstID();
	unsigned getInpID();
	std::vector<std::pair<unsigned,double>* >* getOutPorts();
#ifdef _DEBUG
	void print();
#endif
};
class cef_distributedrouting
{
	protected:	
	std::vector<cef_routing_table*>* tables;			
	public:
	cef_distributedrouting();
	cef_distributedrouting(std::vector<cef_routing_table*>*);
	~cef_distributedrouting();
	//Setters
	void setTables(std::vector<cef_routing_table*>*);
	//Getters
	std::vector<cef_routing_table*>* getTables();
#ifdef _DEBUG
	void print();
#endif
};
class cef_lbdr_fork
{
	protected:
	unsigned input_port_id;
	std::vector<unsigned>* fork_ports;
	public:
	cef_lbdr_fork();
	cef_lbdr_fork(unsigned,std::vector<unsigned>*);
	~cef_lbdr_fork();
	//Setters
	void setInpID(unsigned);
	void setForkPorts(std::vector<unsigned>*);
	//Getters
	unsigned getInpID();
	std::vector<unsigned>* getForkPorts();
#ifdef _DEBUG
	void print();
#endif
	
};
class cef_lbdr_entry
{
	protected:
	unsigned switch_id;
	unsigned long long routing_bits;
	unsigned long long connectivity_bits;
	std::vector<std::pair<unsigned,unsigned>*>* lbdr_deroutes;
	std::vector<cef_lbdr_fork*>* lbdr_forks;
	public:
	cef_lbdr_entry();
	cef_lbdr_entry(unsigned, unsigned long long, unsigned long long, std::vector<std::pair<unsigned,unsigned>* >*, std::vector<cef_lbdr_fork*>*);	
	~cef_lbdr_entry();
	//Setters
	void setSwID(unsigned);
	void setRoutingBits(unsigned long long);
	void setConnectBits(unsigned long long);
	void setDeroutes(std::vector<std::pair<unsigned,unsigned>* >*);
	void setForks(std::vector<cef_lbdr_fork*>* );
	//Getters
	unsigned getSwID();
	unsigned long long getRoutingBits();	
	unsigned long long getConnectBits();
	std::vector<std::pair<unsigned,unsigned>* >* getDeroutes();
	std::vector<cef_lbdr_fork*>* getForks();
#ifdef _DEBUG
	void print();
#endif
};

class cef_lbdr
{
	protected:
	std::vector<cef_lbdr_entry*>* entries;
	public:
	cef_lbdr();
	cef_lbdr(std::vector<cef_lbdr_entry*>*);
	~cef_lbdr();
	//Setters
	void setEntries(std::vector<cef_lbdr_entry*>*);
	//Getters
	std::vector<cef_lbdr_entry*>* getEntries();
#ifdef _DEBUG
	void print();
#endif
};

class cef_fdor
{
	protected:
	std::vector<std::pair<unsigned, unsigned long long>* >* fdor_entries;
	public:
	cef_fdor();
	cef_fdor(std::vector<std::pair<unsigned, unsigned long long>* >*);
	~cef_fdor();
	//Setters
	void setEntries(std::vector<std::pair<unsigned , unsigned long long>* >*);
	//Getters
	std::vector<std::pair<unsigned, unsigned long long>* >* getEntries();
#ifdef _DEBUG
	void print();
#endif
};

class cef_virtual_network
{
	protected:
	unsigned id;
	std::vector<unsigned>* vcs;
	public:
	cef_virtual_network();
	cef_virtual_network(unsigned,std::vector<unsigned>*);
	~cef_virtual_network();
	//Setters
	void setID(unsigned);
	void setVCs(std::vector<unsigned>*);
	//Getters
	unsigned getID();
	std::vector<unsigned>* getVCs();
#ifdef _DEBUG
	void print();
#endif

};

class cef_routes
{
	protected:
	std::string routing_policy;	
	cef_sourcerouting* sourcerouting;
	cef_distributedrouting* distributedrouting;
	cef_lbdr* lbdr;
	cef_fdor* fdor;
	std::vector<cef_virtual_network*>* virtual_networks;
	public:
	cef_routes();
	cef_routes(std::string,cef_sourcerouting*,cef_distributedrouting*, cef_lbdr*, cef_fdor*, std::vector<cef_virtual_network*>*);
	~cef_routes();
	//Setters
	void setRoutingPolicy(std::string);
	void setSourceRouting(cef_sourcerouting*);
	void setDistributedRouting(cef_distributedrouting*);
	void setLBDR(cef_lbdr*);
	void setFDOR(cef_fdor*);
	void setVNs(std::vector<cef_virtual_network*>*);
	//Getters
	std::string getRoutingPolicy();
	cef_sourcerouting* getSourceRouting();
	cef_distributedrouting* getDistributedRouting();
	cef_lbdr* getLBDR();
	cef_fdor* getFDOR();
	std::vector<cef_virtual_network*>* getVNs();	
#ifdef _DEBUG
	void print();
#endif
};
#endif
